<?php
// a encoder to encode the scode, it is a reversible algorithm.
namespace app\scodetrace\encoder;
use \Hashids\Hashids;

class PcodeEncoder {
	const base='0123456789abcdefghijklmnopqrstuvwxyz';
	private $encoder;
	private static $_instance;
	private $prefix='PKC';
	private $length='20';

	public static function getInstance() {
		if (PcodeEncoder::$_instance) {
			return PcodeEncoder::$_instance;
		} else {
			return (PcodeEncoder::$_instance=new PcodeEncoder());
		}
	}

	private function getEncoder() {
		$cache = cache('PcodeEncoder');
		if ($cache) {
			return $cache;
		}

		$data = [];
		$data['encoder'] = new Hashids('xlfwsy_pack',$this->length-strlen($this->prefix),PcodeEncoder::base);
		cache('PcodeEncoder',$data,config('cache_param.pcode_encorder'));
		return $data;
	}


	public function encode($ids) {
		$encoder = $this->getEncoder();
		if (is_array($ids)) {
			$ids2 = [];
			foreach ($ids as $id)
				$ids2[] = $this->prefix.$encoder['encoder']->encode([$id,8141]);
			$ids = $ids2;
		} else {
			$ids = $this->prefix.$encoder['encoder']->encode([$ids,8141]);
		}
		return $ids;
	}

	public function decode($cryptographs) {
		if (!$cryptographs)
			return null;
		$encoder = $this->getEncoder();
		$prefix_len = strlen($this->prefix);
		if (is_array($cryptographs)) {
			$cryptographs['error'] = 0;
			foreach ($cryptographs as $key => $value) {
				if (substr($value,0,$prefix_len)==$this->prefix)
					$cryptographs[$key] = $this->_decode(substr($value,$prefix_len),$encoder);
				else {
					$cryptographs[$key] = null;
					$cryptographs['error']++;
				}
			}
		} else {
			if (substr($cryptographs,0,$prefix_len)==$this->prefix)
				$cryptographs = $this->_decode(substr($cryptographs,$prefix_len),$encoder);
			else
				$cryptographs = null;
		}
		return $cryptographs;
	}

	public function _decode($cryptograph, $encoder) {
		$tmp = $encoder['encoder']->decode($cryptograph);
		if (count($tmp) != 2 || $tmp[1] != 8141) {
			return null;
		}
		return $tmp[0];
	}
}





?>